package cn.edu.xmut.chen.zhlg.common.HttpResult;


import cn.edu.xmut.chen.zhlg.common.framework.exception.AssertionException;
import cn.edu.xmut.chen.zhlg.common.utils.ResultType;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求返回结果对象
 *
 * @author bill.lin
 */

@Data
public class Result implements Serializable {

	@ApiModelProperty(value = "返回状态编码 200 操作成功；400 操作失败；401 权限不足；404 接口不存在；500 服务器内部错误；600 请重新登录")
	protected String statusCode;

	@ApiModelProperty(value = "返回提示信息")
	protected String message;

	@ApiModelProperty(value = "返回结果数据")
	protected Object data;

    /**
     * 私有化默认构造，只能通过静态方法构造对象
     */
    private Result() {
    }

    /**
     * 设置返回消息
     *
     * @param message 消息 String
     * @return this
     */
    public Result message(String message) {
        this.message = message;
        return this;
    }

    /**
     * 设置返回的一个对象
     * <p color="red">最多只能存在一个对象，多次调用覆盖 !</p>
     *
     * @param data 任意类型 Object
     * @return this
     */
    public Result data(Object data) {
        this.data = data;
        return this;
    }

    /**
     * 设置返回 Map 的数据
     * <p>逻辑不对不抛出异常，如果原本 data 不是 Map 类型，则直接替换</p>
     *
     * @param key   数据键 String
     * @param value 数据值 Object
     * @return this
     */
    public Result put(String key, Object value) {
        if (!(this.data instanceof Map)) {
            this.data = new HashMap<String, Object>();
        }
        ((HashMap<String, Object>) data).put(key, value);
        return this;
    }

    /**
     * 设置状态编码
     *
     * @param resultType 状态类型枚举 ResultType
     * @return this
     */
    public Result setStatusCode(ResultType resultType) {
        this.statusCode = resultType.getCode();
        return this;
    }

    /**
     * 设置状态编码
     *
     * @param statusCode 状态编码 数字 String
     * @return this
     */
    public Result setStatusCode(String statusCode) {
        this.statusCode = statusCode;
        return this;
    }

    public static Result fail() {
        return fail("");
    }

    public static Result fail(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.FAIL);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.FAIL.getName();
        }
        return result;
    }

    public static Result fail(Exception e) {
        if (e instanceof AssertionException) {
            return fail((AssertionException) e);
        } else {
            return fail();
        }
    }

    public static Result fail(ResultType resultType) {
        Result result = new Result().setStatusCode(resultType);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.FAIL.getName();
        }
        return result;
    }

    public static Result fail(AssertionException e) {
        Result result = new Result().message(e.getMessage()).setStatusCode(e.getResultType());
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.FAIL.getName();
        }
        return result;
    }

    public static Result error() {
        return error("");
    }

    public static Result error(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.INTERNAL_SERVER_ERROR);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.INTERNAL_SERVER_ERROR.getName();
        }
        return result;
    }

    public static Result success() {
        return success("");
    }

    public static Result success(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.SUCCESS);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.SUCCESS.getName();
        }
        return result;
    }

    public static Result success(Object data) {
        Result result = new Result()
                .data(data)
                .setStatusCode(ResultType.SUCCESS);

        if (result.getMessage() == null || result.getMessage().isEmpty()) {
            result.message(ResultType.SUCCESS.getName());
        }
        return result;
    }

    public static Result unauthorized() {
        return unauthorized("");
    }

    public static Result unauthorized(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.UNAUTHORIZED);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.UNAUTHORIZED.getName();
        }
        return result;
    }

    public static Result notFound() {
        return notFound("");
    }

    public static Result notFound(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.NOT_FOUND);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.NOT_FOUND.getName();
        }
        return result;
    }

    public static Result againLogin() {
        return againLogin("");
    }

    public static Result againLogin(String message) {
        Result result = new Result().message(message).setStatusCode(ResultType.AGAIN_LOGIN);
        if (result.message == null || "".equals(result.message)) {
            result.message = ResultType.AGAIN_LOGIN.getName();
        }
        return result;
    }
}
